package it.polimi.swKnights.SWIMv2.ejb.registration;

import java.util.List;
import java.util.Set;

import it.polimi.swKnights.SWIMv2.ejb.authentication.LoginHandlerLocal;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.Feedback;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.Founder;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.FriendshipRequest;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.PrivateMessage;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.ReceivedMessages;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.RegisteredUser;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.CannotDeleteFounderAccountException;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.InvalidLoginPrivilegesException;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.LoginFailException;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.collections.Factory;
import org.hibernate.SQLQuery;
import org.hibernate.Session;

/**
 * Session Bean implementation class DeleteAccount
 */
@Stateless
public class DeleteAccount implements DeleteAccountRemote
{

	@PersistenceContext(unitName = "swimv2-manager")
	private EntityManager managerUC; // manager handling the persistence data

	@EJB
	private LoginHandlerLocal loginController;

	@Override
	public void deleteAccountOfUser(String username, String password,
			String email) throws LoginFailException,
			CannotDeleteFounderAccountException, InvalidLoginPrivilegesException
	{
		this.loginController.checkLoginDataAndPrivileges(username, password,
				RegisteredUser.class);
		RegisteredUser registeredUser = managerUC.getReference(
				RegisteredUser.class, username);
		
		//friendship will go away thank to the CASCADE annotation
		
		this.deleteAbilitiesOf(registeredUser);
		this.deleteReceivedMessages(registeredUser);
		this.deleteFriendRequest(registeredUser);
		this.updateSentMessage(registeredUser);
		this.deleteReceivedFeedback(registeredUser);
		this.updateLeftFeedback(registeredUser);
		
		
		
		Founder founderUser = managerUC.find(Founder.class, username);
		if (founderUser != null)
		{
			throw new CannotDeleteFounderAccountException(
					"cannot delete founder account");
		}

		managerUC.remove(registeredUser);

	}

	private void deleteReceivedFeedback(RegisteredUser registeredUser) {
		String s = "FROM Feedback f WHERE f.gotByUser=:gotBy";
		Query query = this.managerUC.createQuery(s);
		query.setParameter("gotBy", registeredUser);
		
		List<?> list = query.getResultList();
		for(Object o: list)
		{
			if(o instanceof Feedback)
			{
				Feedback f = (Feedback) o;
				this.managerUC.remove(f);
			}
				
		}
		
	}

	private void updateLeftFeedback(RegisteredUser leftBy) {
		String s = "FROM Feedback f WHERE f.leftBy=:leftBy";
		Query query = this.managerUC.createQuery(s);
		query.setParameter("leftBy", leftBy);
		
		List<?> list = query.getResultList();
		for(Object o: list)
		{
			if(o instanceof Feedback)
			{
				Feedback f = (Feedback) o;
				f.setLeftBy(null);
			}
				
		}
		
	}

	private void updateSentMessage(RegisteredUser sender) {
		
		String s = "FROM PrivateMessage pm WHERE pm.sent_by=:sender";
		
		Query query = this.managerUC.createQuery(s);
		
		query.setParameter("sender", sender.getUserName());
		List<?> list = query.getResultList();
		for(Object o: list)
		{
			if(o instanceof PrivateMessage)
			{
				PrivateMessage pm = (PrivateMessage) o;
				pm.setSender(null);
			}
				
		}
		
	
		
	}

	private void deleteAbilitiesOf(RegisteredUser registeredUser) {
		
		registeredUser.removeAllAbilities();
		managerUC.persist(registeredUser);
	}

	private void deleteReceivedMessages(RegisteredUser registeredUser) {
		  
		List<ReceivedMessages> lstMessages = registeredUser.getReceivedMessages();
		
		for(ReceivedMessages rm : lstMessages)
		{
			managerUC.remove(rm);
			
		}
		managerUC.persist(registeredUser);
		
	}

	private void deleteFriendRequest(RegisteredUser registeredUser)
	{
		Set<FriendshipRequest> setFriendshReq = registeredUser.getFriendshipRequests();
		for( FriendshipRequest f : setFriendshReq )
		{
			
			managerUC.remove(f);
		}
		managerUC.persist(registeredUser);
		
		//delet who asked me and who i asked to
		
		
		String findMessagesQuery = ""
				+ "DELETE FROM FriendshipRequest AS fr "
				+ "WHERE (fr.applicantName=:userName OR fr.requestedName=:userName) "
					;

		String userName = registeredUser.getUserName();
		Query query = this.managerUC.createQuery(findMessagesQuery);
		query.setParameter("userName", userName);
		query.executeUpdate();
		
		
		
		
	}

}
